﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IridiumDB.Model;
using IridiumDB.Services;
using IridiumFlares;
using System.Globalization;

namespace FlaresAtHand
{
    public partial class LocationForm : Form
    {
        private DatabaseService _service;
        private List<Location> _locations;

        public LocationForm()
        {
            InitializeComponent();
            using (var actions = new ActionForm())
            {
                actions.Log("Starting Database ...");
                _service = new DatabaseService();
                //TestDataInit();
                actions.Log("Loading locations from DB ...");
                LoadLocations();
                actions.Log("Ready!");
            }
        }

        private void LoadLocations()
        {
            _locations = _service.LocationRepository.FindAll();
            dataGridLocations.DataSource = (from location in _locations
                                            select new
                                            {
                                                LocationName = location.LocationName,
                                                Altitude = location.Altitude,
                                                GpsLat = location.GpsLat,
                                                GpsLong = location.GpsLong,
                                                PreviewDuration = location.PreviewDuration,
                                                TimezoneName = location.TimezoneName
                                            }).ToList();
            BuildLocationMenu();
        }

        private void TestDataInit()
        {
            Location location = new Location
            {
                LocationName = "Berg am Laim",
                Altitude = 523,
                TimezoneName = "CET",
                GpsLat = 48.133F,
                GpsLong = 11.633F,
                PreviewDuration = 7
            };
            bool newLocation = _service.AddNewLocation(location);
        }

        private void BuildLocationMenu()
        {
            foreach (var loc in _locations)
            {
                var locationItem = new MenuItem();
                locationItem.Text = loc.LocationName;
                locationItem.Click += miViewLocation_Click;
                miView.MenuItems.Add(locationItem);
            }
        }

        private int AddFlaresForLocation(Location location, out List<Flare> nonUniqueFlares)
        {
            String url = location.LocationUrl;
            var parser = new PageParser(url);
            var flares = parser.parse();
            return _service.AddNewFlares(flares, location, out nonUniqueFlares);
        }

        private void miLocationSave_Click(object sender, EventArgs e)
        {

            Location location;
            String validationErrors = ValidateLocationInput(tbLocationName.Text.Trim(), tbLocationAlt.Text.Trim(), tbLocationTimezone.Text.Trim(),
                tbLocationLat.Text.Trim(), tbLocationLong.Text.Trim(), tbLocationPreviewDuration.Text.Trim(), out location);

            if (validationErrors == null)
            {
                bool newLocation = _service.AddNewLocation(location);
                if (newLocation)
                {
                    LoadLocations();
                }
            }
            else
            {
                MessageBox.Show(validationErrors);
            }
        }

        private String ValidateLocationInput(String name, String altitude, String timezone,
            String latitude, String longitude, String duration, out Location location)
        {
            StringBuilder errors = new StringBuilder();
            if (String.IsNullOrEmpty(name)) errors.AppendLine("Name is empty.");
            if (String.IsNullOrEmpty(altitude)) errors.AppendLine("Altitude is empty.");
            if (String.IsNullOrEmpty(timezone)) errors.AppendLine("Timezone is empty.");
            if (String.IsNullOrEmpty(latitude)) errors.AppendLine("Latitude is empty.");
            if (String.IsNullOrEmpty(longitude)) errors.AppendLine("Longitude is empty.");
            if (String.IsNullOrEmpty(duration)) errors.AppendLine("Duration is empty.");

            bool errorFree = errors.Length == 0;

            if (errorFree)
            {
                location = new Location
                {
                    LocationName = name.ToString(CultureInfo.InvariantCulture),
                    Altitude = int.Parse(altitude, CultureInfo.InvariantCulture),
                    TimezoneName = timezone,
                    GpsLat = float.Parse(latitude, CultureInfo.InvariantCulture),
                    GpsLong = float.Parse(longitude, CultureInfo.InvariantCulture),
                    PreviewDuration = int.Parse(duration, CultureInfo.InvariantCulture)
                };
            }
            else
            {
                location = null;
            }

            return errorFree ? null : errors.ToString();
        }

        private void miUpdateAll_Click(object sender, EventArgs e)
        {
            using (var actions = new ActionForm())
            {
                var locations = _service.LocationRepository.FindAll();
                actions.Log(String.Format("Going to update {0} locations", locations.Count));
                Logger.Log(String.Format("Going to update {0} locations", locations.Count));
                foreach (var loc in locations)
                {
                    Logger.Log(String.Format("Using Url {0}", loc.LocationUrl));
                    List<Flare> notAddedFlares;
                    int newFlares = AddFlaresForLocation(loc, out notAddedFlares);
                    actions.Log(String.Format("{0} new flares for location {1}", newFlares, loc.LocationName));
                    Logger.Log(String.Format("{0} new flares for location {1}", newFlares, loc.LocationName));
                    int updates = _service.UpdateFlares(notAddedFlares.ToArray(), loc);
                    actions.Log(String.Format("{0} updates for location {1}", updates, loc.LocationName));
                    Logger.Log(String.Format("{0} updates for location {1}", updates, loc.LocationName));
                }
                actions.Log("Done updating");
            }
        }

        private void miViewLocation_Click(object sender, EventArgs e)
        {
            var menuItem = sender as MenuItem;
            var location = (from loc in _locations
                            where loc.LocationName == menuItem.Text
                            select loc).Single();

            var flareForm = new FlareForm();
            flareForm.ShowFlares(_service.FlareEntryRepository.FindAllUpcomingForLocationId(location.ID));
            flareForm.Show();
        }
    }
}